summaryrefslogtreecommitdiffabout
path: root/gammu/emb
authorzautrix <zautrix>2004-08-30 20:21:20 (UTC)
committer zautrix <zautrix>2004-08-30 20:21:20 (UTC)
commit109a23b70f67552a9ce27f682bb2b1bdbb2bb4f3 (patch) (unidiff)
tree30407f1548315b403f1ad7c55c81744413fcd14c /gammu/emb
parent5f4867356dc4b34da20b66e9ede71e22899e4a4b (diff)
downloadkdepimpi-109a23b70f67552a9ce27f682bb2b1bdbb2bb4f3.zip
kdepimpi-109a23b70f67552a9ce27f682bb2b1bdbb2bb4f3.tar.gz
kdepimpi-109a23b70f67552a9ce27f682bb2b1bdbb2bb4f3.tar.bz2
sine fix
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,1601 +1,1605 @@
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
1133 strcpy(dest->NokiaBinary.Frame+current,"\x02\xFC\x09");current=current+3; 1137 strcpy(dest->NokiaBinary.Frame+current,"\x02\xFC\x09");current=current+3;
1134 dest->NokiaBinary.Frame[current++]=0x00; 1138 dest->NokiaBinary.Frame[current++]=0x00;
1135 1139
1136 /*This command can be used to loop, where 0xLL = 0x01 - 0x10 1140 /*This command can be used to loop, where 0xLL = 0x01 - 0x10
1137 *0x01=loop once [...] 0x10=loop infinite 1141 *0x01=loop once [...] 0x10=loop infinite
1138 *Commented now 1142 *Commented now
1139 1143
1140 dest->NokiaBinary.Frame[current++]=0x05; 1144 dest->NokiaBinary.Frame[current++]=0x05;
1141 dest->NokiaBinary.Frame[current++]=0xLL; 1145 dest->NokiaBinary.Frame[current++]=0xLL;
1142 */ 1146 */
1143 strcpy(dest->NokiaBinary.Frame+current,"\x0A\x01");current=current+2; 1147 strcpy(dest->NokiaBinary.Frame+current,"\x0A\x01");current=current+2;
1144 1148
1145 for (i=0; i<src->NoteTone.NrCommands; i++) { 1149 for (i=0; i<src->NoteTone.NrCommands; i++) {
1146 if (src->NoteTone.Commands[i].Type != RING_Note) continue; 1150 if (src->NoteTone.Commands[i].Type != RING_Note) continue;
1147 1151
1148 Note = &src->NoteTone.Commands[i].Note; 1152 Note = &src->NoteTone.Commands[i].Note;
1149 note = 64; /* Pause */ 1153 note = 64; /* Pause */
1150 if (Note->Note!=Note_Pause) { 1154 if (Note->Note!=Note_Pause) {
1151 if (Note->Note >= Note_C && Note->Note <= Note_H) { 1155 if (Note->Note >= Note_C && Note->Note <= Note_H) {
1152 note = 113 + Note->Note/16; 1156 note = 113 + Note->Note/16;
1153 } 1157 }
1154 switch (Note->Scale) { 1158 switch (Note->Scale) {
1155 case Scale_440 : break; 1159 case Scale_440 : break;
1156 case Scale_880 : note = note + 12; break; 1160 case Scale_880 : note = note + 12; break;
1157 case Scale_1760: note = note + 24;break; 1161 case Scale_1760: note = note + 24;break;
1158 case Scale_3520: note = note + 36; break; 1162 case Scale_3520: note = note + 36; break;
1159 default : break; 1163 default : break;
1160 } 1164 }
1161 } 1165 }
1162 1166
1163 /* In 7110 we have 8 ms long sounds */ 1167 /* In 7110 we have 8 ms long sounds */
1164 duration = 60000 * GSM_RingNoteGetFullDuration(*Note) / Note->Tempo / 256; 1168 duration = 60000 * GSM_RingNoteGetFullDuration(*Note) / Note->Tempo / 256;
1165 1169
1166 switch (Note->Style) { 1170 switch (Note->Style) {
1167 case StaccatoStyle: 1171 case StaccatoStyle:
1168 if (duration) { 1172 if (duration) {
1169 /* Note needs only one sound */ 1173 /* Note needs only one sound */
1170 dest->NokiaBinary.Frame[current++] = note; 1174 dest->NokiaBinary.Frame[current++] = note;
1171 dest->NokiaBinary.Frame[current++] = 1; 1175 dest->NokiaBinary.Frame[current++] = 1;
1172 duration--; 1176 duration--;
1173 } 1177 }
1174 note = 0x40; /* The rest is pause */ 1178 note = 0x40; /* The rest is pause */
1175 case NaturalStyle: 1179 case NaturalStyle:
1176 if (note != 0x40 && duration) { 1180 if (note != 0x40 && duration) {
1177 dest->NokiaBinary.Frame[current++] = 0x40; 1181 dest->NokiaBinary.Frame[current++] = 0x40;
1178 /* There is small pause between notes */ 1182 /* There is small pause between notes */
1179 dest->NokiaBinary.Frame[current++] = 1; 1183 dest->NokiaBinary.Frame[current++] = 1;
1180 duration--; 1184 duration--;
1181 } 1185 }
1182 default: 1186 default:
1183 if (note != 0x40 && note == lastnote && duration) { 1187 if (note != 0x40 && note == lastnote && duration) {
1184 dest->NokiaBinary.Frame[current++] = 0x40; 1188 dest->NokiaBinary.Frame[current++] = 0x40;
1185 /* There is small pause between same notes */ 1189 /* There is small pause between same notes */
1186 dest->NokiaBinary.Frame[current++] = 1; 1190 dest->NokiaBinary.Frame[current++] = 1;
1187 duration--; 1191 duration--;
1188 } 1192 }
1189 while (duration > 125) { 1193 while (duration > 125) {
1190 dest->NokiaBinary.Frame[current++] = note; 1194 dest->NokiaBinary.Frame[current++] = note;
1191 dest->NokiaBinary.Frame[current++] = 125; 1195 dest->NokiaBinary.Frame[current++] = 125;
1192 duration -= 125; 1196 duration -= 125;
1193 } 1197 }
1194 dest->NokiaBinary.Frame[current++] = note; 1198 dest->NokiaBinary.Frame[current++] = note;
1195 dest->NokiaBinary.Frame[current++] = duration; 1199 dest->NokiaBinary.Frame[current++] = duration;
1196 } 1200 }
1197 lastnote = note; 1201 lastnote = note;
1198 } 1202 }
1199 for (i = 0; i < (int)sizeof(end); i++) dest->NokiaBinary.Frame[current++] = end[i]; 1203 for (i = 0; i < (int)sizeof(end); i++) dest->NokiaBinary.Frame[current++] = end[i];
1200 dest->NokiaBinary.Length=current; 1204 dest->NokiaBinary.Length=current;
1201} 1205}
1202 1206
1203static void Binary2RTTL(GSM_Ringtone *dest, GSM_Ringtone *src) 1207static void Binary2RTTL(GSM_Ringtone *dest, GSM_Ringtone *src)
1204{ 1208{
1205 int i = 3, j, z, NrNotes = 0, repeat = 0, accuracy; 1209 int i = 3, j, z, NrNotes = 0, repeat = 0, accuracy;
1206 int StartRepeat = 0, EndRepeat, Speed; 1210 int StartRepeat = 0, EndRepeat, Speed;
1207 unsigned char command,length=0; 1211 unsigned char command,length=0;
1208 int NotesLen[500]; 1212 int NotesLen[500];
1209 GSM_RingNoteScale NotesScale[500]; 1213 GSM_RingNoteScale NotesScale[500];
1210 GSM_RingNoteNote Notes[500]; 1214 GSM_RingNoteNote Notes[500];
1211 int Lengths[6*4]; 1215 int Lengths[6*4];
1212 GSM_RingNoteDurationSpec DurationSpec[6*4]; 1216 GSM_RingNoteDurationSpec DurationSpec[6*4];
1213 GSM_RingNoteDuration Duration[6*4]; 1217 GSM_RingNoteDuration Duration[6*4];
1214 bool foundlen; 1218 bool foundlen;
1215 GSM_RingNote *Note; 1219 GSM_RingNote *Note;
1216 1220
1217 while (i<src->NokiaBinary.Length) { 1221 while (i<src->NokiaBinary.Length) {
1218 command = src->NokiaBinary.Frame[i]; 1222 command = src->NokiaBinary.Frame[i];
1219 i++; 1223 i++;
1220 if (command != 0x06 && command != 0x00 && command != 0x09) { 1224 if (command != 0x06 && command != 0x00 && command != 0x09) {
1221 length = src->NokiaBinary.Frame[i]; 1225 length = src->NokiaBinary.Frame[i];
1222 i++; 1226 i++;
1223 dbgprintf("Block %02x %02x - ",length,command); 1227 dbgprintf("Block %02x %02x - ",length,command);
1224 } else dbgprintf("Block %02x - ",command); 1228 } else dbgprintf("Block %02x - ",command);
1225 if (command >= 114 && command <= 161) { 1229 if (command >= 114 && command <= 161) {
1226 dbgprintf("note\n"); 1230 dbgprintf("note\n");
1227 if (command >= 114 && command <= 124) { 1231 if (command >= 114 && command <= 124) {
1228 NotesScale[NrNotes] = Scale_440; command -= 114; 1232 NotesScale[NrNotes] = Scale_440; command -= 114;
1229 } else if (command >= 125 && command <= 137) { 1233 } else if (command >= 125 && command <= 137) {
1230 NotesScale[NrNotes] = Scale_880; command -= 126; 1234 NotesScale[NrNotes] = Scale_880; command -= 126;
1231 } else if (command >= 138 && command <= 149) { 1235 } else if (command >= 138 && command <= 149) {
1232 NotesScale[NrNotes] = Scale_1760; command -= 138; 1236 NotesScale[NrNotes] = Scale_1760; command -= 138;
1233 } else if (command >= 150 && command <= 161) { 1237 } else if (command >= 150 && command <= 161) {
1234 NotesScale[NrNotes] = Scale_3520; command -= 150; 1238 NotesScale[NrNotes] = Scale_3520; command -= 150;
1235 } 1239 }
1236 switch (command) { 1240 switch (command) {
1237 case 0 : Notes[NrNotes] = Note_C;break; 1241 case 0 : Notes[NrNotes] = Note_C;break;
1238 case 1 : Notes[NrNotes] = Note_Cis;break; 1242 case 1 : Notes[NrNotes] = Note_Cis;break;
1239 case 2 : Notes[NrNotes] = Note_D;break; 1243 case 2 : Notes[NrNotes] = Note_D;break;
1240 case 3 : Notes[NrNotes] = Note_Dis;break; 1244 case 3 : Notes[NrNotes] = Note_Dis;break;
1241 case 4 : Notes[NrNotes] = Note_E;break; 1245 case 4 : Notes[NrNotes] = Note_E;break;
1242 case 5 : Notes[NrNotes] = Note_F;break; 1246 case 5 : Notes[NrNotes] = Note_F;break;
1243 case 6 : Notes[NrNotes] = Note_Fis;break; 1247 case 6 : Notes[NrNotes] = Note_Fis;break;
1244 case 7 : Notes[NrNotes] = Note_G;break; 1248 case 7 : Notes[NrNotes] = Note_G;break;
1245 case 8 : Notes[NrNotes] = Note_Gis;break; 1249 case 8 : Notes[NrNotes] = Note_Gis;break;
1246 case 9 : Notes[NrNotes] = Note_A;break; 1250 case 9 : Notes[NrNotes] = Note_A;break;
1247 case 10 : Notes[NrNotes] = Note_Ais;break; 1251 case 10 : Notes[NrNotes] = Note_Ais;break;
1248 case 11 : Notes[NrNotes] = Note_H;break; 1252 case 11 : Notes[NrNotes] = Note_H;break;
1249 } 1253 }
1250 if (NrNotes > 0) { 1254 if (NrNotes > 0) {
1251 if (Notes[NrNotes-1] == Notes[NrNotes] && 1255 if (Notes[NrNotes-1] == Notes[NrNotes] &&
1252 NotesScale[NrNotes-1] == NotesScale[NrNotes]) { 1256 NotesScale[NrNotes-1] == NotesScale[NrNotes]) {
1253 NotesLen[NrNotes-1]+=length; 1257 NotesLen[NrNotes-1]+=length;
1254 } else { 1258 } else {
1255 NotesLen[NrNotes]=length; 1259 NotesLen[NrNotes]=length;
1256 NrNotes++; 1260 NrNotes++;
1257 } 1261 }
1258 } else { 1262 } else {
1259 NotesLen[NrNotes]=length; 1263 NotesLen[NrNotes]=length;
1260 NrNotes++; 1264 NrNotes++;
1261 } 1265 }
1262 } else switch (command) { 1266 } else switch (command) {
1263 case 0x00: 1267 case 0x00:
1264 dbgprintf("Unknown\n"); 1268 dbgprintf("Unknown\n");
1265 break; 1269 break;
1266 case 0x05: 1270 case 0x05:
1267 dbgprintf("repeat %i times\n",length); 1271 dbgprintf("repeat %i times\n",length);
1268 repeat = length; 1272 repeat = length;
1269 StartRepeat = NrNotes; 1273 StartRepeat = NrNotes;
1270 break; 1274 break;
1271 case 0x06: 1275 case 0x06:
1272 dbgprintf("end repeat\n"); 1276 dbgprintf("end repeat\n");
1273 EndRepeat = NrNotes; 1277 EndRepeat = NrNotes;
1274 for (z=0;z<repeat-1;z++) { 1278 for (z=0;z<repeat-1;z++) {
1275 for (j=StartRepeat;j<EndRepeat;j++) { 1279 for (j=StartRepeat;j<EndRepeat;j++) {
1276 Notes[NrNotes] = Notes[j]; 1280 Notes[NrNotes] = Notes[j];
1277 NotesScale[NrNotes] = NotesScale[j]; 1281 NotesScale[NrNotes] = NotesScale[j];
1278 NotesLen[NrNotes] = NotesLen[j]; 1282 NotesLen[NrNotes] = NotesLen[j];
1279 NrNotes++; 1283 NrNotes++;
1280 dbgprintf("Adding repeat note %i %i\n",Notes[j],NotesLen[j]); 1284 dbgprintf("Adding repeat note %i %i\n",Notes[j],NotesLen[j]);
1281 } 1285 }
1282 } 1286 }
1283 break; 1287 break;
1284 case 0x07: 1288 case 0x07:
1285 if (length == 0x0B) { 1289 if (length == 0x0B) {
1286 dbgprintf("Ringtone end\n"); 1290 dbgprintf("Ringtone end\n");
1287 i = src->NokiaBinary.Length + 1; 1291 i = src->NokiaBinary.Length + 1;
1288 } 1292 }
1289 break; 1293 break;
1290 case 0x09: 1294 case 0x09:
1291 dbgprintf("Unknown\n"); 1295 dbgprintf("Unknown\n");
1292 break; 1296 break;
1293 case 0x0A: 1297 case 0x0A:
1294 if (length == 0x01) { 1298 if (length == 0x01) {
1295 dbgprintf("Let's start our song\n"); 1299 dbgprintf("Let's start our song\n");
1296 break; 1300 break;
1297 } 1301 }
1298 if (length == 0x0A) { 1302 if (length == 0x0A) {
1299 dbgprintf("Ending joining note\n"); 1303 dbgprintf("Ending joining note\n");
1300 break; 1304 break;
1301 } 1305 }
1302 if (length == 0xFE) { 1306 if (length == 0xFE) {
1303 dbgprintf("Starting joining note\n"); 1307 dbgprintf("Starting joining note\n");
1304 break; 1308 break;
1305 } 1309 }
1306 break; 1310 break;
1307 case 0x40: 1311 case 0x40:
1308 dbgprintf("Pause\n"); 1312 dbgprintf("Pause\n");
1309 Notes[NrNotes] = Note_Pause; 1313 Notes[NrNotes] = Note_Pause;
1310 if (NrNotes > 0) { 1314 if (NrNotes > 0) {
1311 if (Notes[NrNotes-1] == Notes[NrNotes] && 1315 if (Notes[NrNotes-1] == Notes[NrNotes] &&
1312 NotesScale[NrNotes-1] == NotesScale[NrNotes]) { 1316 NotesScale[NrNotes-1] == NotesScale[NrNotes]) {
1313 NotesLen[NrNotes-1]+=length; 1317 NotesLen[NrNotes-1]+=length;
1314 } else { 1318 } else {
1315 NotesLen[NrNotes]=length; 1319 NotesLen[NrNotes]=length;
1316 NrNotes++; 1320 NrNotes++;
1317 } 1321 }
1318 } else { 1322 } else {
1319 NotesLen[NrNotes]=length; 1323 NotesLen[NrNotes]=length;
1320 NrNotes++; 1324 NrNotes++;
1321 } 1325 }
1322 break; 1326 break;
1323 default: 1327 default:
1324 dbgprintf("Unknown\n"); 1328 dbgprintf("Unknown\n");
1325 } 1329 }
1326 } 1330 }
1327 1331
1328 while (NrNotes>0) { 1332 while (NrNotes>0) {
1329 if (Notes[NrNotes-1] == Note_Pause) { 1333 if (Notes[NrNotes-1] == Note_Pause) {
1330 NrNotes--; 1334 NrNotes--;
1331 } else break; 1335 } else break;
1332 } 1336 }
1333 1337
1334 for (accuracy=1; accuracy<5; accuracy++) { 1338 for (accuracy=1; accuracy<5; accuracy++) {
1335 i = 1; 1339 i = 1;
1336 while (i < 1000) { 1340 while (i < 1000) {
1337 Lengths[0] = 30000/i; 1341 Lengths[0] = 30000/i;
1338 for (j=0;j<5;j++) Lengths[j+1] = Lengths[j] / 2; 1342 for (j=0;j<5;j++) Lengths[j+1] = Lengths[j] / 2;
1339 for (j=0;j<6;j++) Lengths[6+j] = Lengths[j] * 3/2; 1343 for (j=0;j<6;j++) Lengths[6+j] = Lengths[j] * 3/2;
1340 for (j=0;j<6;j++) Lengths[12+j] = Lengths[j] * 9/4; 1344 for (j=0;j<6;j++) Lengths[12+j] = Lengths[j] * 9/4;
1341 for (j=0;j<6;j++) Lengths[18+j] = Lengths[j] * 2/3; 1345 for (j=0;j<6;j++) Lengths[18+j] = Lengths[j] * 2/3;
1342 1346
1343#ifdef DEBUG 1347#ifdef DEBUG
1344 dbgprintf("Length matrix (%i) : ",i); 1348 dbgprintf("Length matrix (%i) : ",i);
1345 for (j=0;j<6*4;j++) dbgprintf("%i ",Lengths[j]); 1349 for (j=0;j<6*4;j++) dbgprintf("%i ",Lengths[j]);
1346 dbgprintf("\n"); 1350 dbgprintf("\n");
1347#endif 1351#endif
1348 foundlen = false; 1352 foundlen = false;
1349 1353
1350 for (j=0;j<NrNotes;j++) { 1354 for (j=0;j<NrNotes;j++) {
1351 dbgprintf("Comparing to %i\n",NotesLen[j]); 1355 dbgprintf("Comparing to %i\n",NotesLen[j]);
1352 foundlen = false; 1356 foundlen = false;
1353 for (z=0;z<6*4;z++) { 1357 for (z=0;z<6*4;z++) {
1354 if (NotesLen[j] - Lengths[z] > -accuracy && 1358 if (NotesLen[j] - Lengths[z] > -accuracy &&
1355 NotesLen[j] - Lengths[z] < accuracy) { 1359 NotesLen[j] - Lengths[z] < accuracy) {
1356 foundlen = true; 1360 foundlen = true;
1357 break; 1361 break;
1358 } 1362 }
1359 } 1363 }
1360 if (!foundlen) break; 1364 if (!foundlen) break;
1361 } 1365 }
1362 if (foundlen) break; 1366 if (foundlen) break;
1363 i++; 1367 i++;
1364 } 1368 }
1365 1369
1366 if (foundlen) { 1370 if (foundlen) {
1367 Speed = i; 1371 Speed = i;
1368 Duration[5] = Duration_1_32; Duration[4] = Duration_1_16; 1372 Duration[5] = Duration_1_32; Duration[4] = Duration_1_16;
1369 Duration[3] = Duration_1_8; Duration[2] = Duration_1_4; 1373 Duration[3] = Duration_1_8; Duration[2] = Duration_1_4;
1370 Duration[1] = Duration_1_2; Duration[0] = Duration_Full; 1374 Duration[1] = Duration_1_2; Duration[0] = Duration_Full;
1371 for (i=0;i<6;i++) Duration[i] = Duration[i]; 1375 for (i=0;i<6;i++) Duration[i] = Duration[i];
1372 for (i=0;i<6;i++) Duration[i+6] = Duration[i]; 1376 for (i=0;i<6;i++) Duration[i+6] = Duration[i];
1373 for (i=0;i<6;i++) Duration[i+12] = Duration[i]; 1377 for (i=0;i<6;i++) Duration[i+12] = Duration[i];
1374 for (i=0;i<6;i++) Duration[i+18] = Duration[i]; 1378 for (i=0;i<6;i++) Duration[i+18] = Duration[i];
1375 for (i=0;i<6;i++) DurationSpec[i] = NoSpecialDuration; 1379 for (i=0;i<6;i++) DurationSpec[i] = NoSpecialDuration;
1376 for (i=0;i<6;i++) DurationSpec[i+6] = DottedNote; 1380 for (i=0;i<6;i++) DurationSpec[i+6] = DottedNote;
1377 for (i=0;i<6;i++) DurationSpec[i+12] = DoubleDottedNote; 1381 for (i=0;i<6;i++) DurationSpec[i+12] = DoubleDottedNote;
1378 for (i=0;i<6;i++) DurationSpec[i+18] = Length_2_3; 1382 for (i=0;i<6;i++) DurationSpec[i+18] = Length_2_3;
1379 1383
1380 for (i=0;i<NrNotes;i++) { 1384 for (i=0;i<NrNotes;i++) {
1381 dest->NoteTone.Commands[i].Type= RING_Note; 1385 dest->NoteTone.Commands[i].Type= RING_Note;
1382 Note = &dest->NoteTone.Commands[i].Note; 1386 Note = &dest->NoteTone.Commands[i].Note;
1383 Note->Note = Notes[i]; 1387 Note->Note = Notes[i];
1384 Note->Tempo = Speed; 1388 Note->Tempo = Speed;
1385 Note->Style = ContinuousStyle; 1389 Note->Style = ContinuousStyle;
1386 if (Notes[i] != Note_Pause) Note->Scale = NotesScale[i]; 1390 if (Notes[i] != Note_Pause) Note->Scale = NotesScale[i];
1387 for (z=0;z<6*4;z++) { 1391 for (z=0;z<6*4;z++) {
1388 if (NotesLen[i] - Lengths[z] > -accuracy && 1392 if (NotesLen[i] - Lengths[z] > -accuracy &&
1389 NotesLen[i] - Lengths[z] < accuracy) { 1393 NotesLen[i] - Lengths[z] < accuracy) {
1390 Note->Duration = Duration[z]; 1394 Note->Duration = Duration[z];
1391 Note->DurationSpec = DurationSpec[z]; 1395 Note->DurationSpec = DurationSpec[z];
1392 /* Trick from PPM Edit */ 1396 /* Trick from PPM Edit */
1393 if (Note->DurationSpec == DoubleDottedNote) { 1397 if (Note->DurationSpec == DoubleDottedNote) {
1394 switch (Note->Duration) { 1398 switch (Note->Duration) {
1395 case Duration_Full:Note->Duration = Duration_Full;break; 1399 case Duration_Full:Note->Duration = Duration_Full;break;
1396 case Duration_1_2 :Note->Duration = Duration_Full;break; 1400 case Duration_1_2 :Note->Duration = Duration_Full;break;
1397 case Duration_1_4 :Note->Duration = Duration_1_2; break; 1401 case Duration_1_4 :Note->Duration = Duration_1_2; break;
1398 case Duration_1_8 :Note->Duration = Duration_1_4; break; 1402 case Duration_1_8 :Note->Duration = Duration_1_4; break;
1399 case Duration_1_16:Note->Duration = Duration_1_8; break; 1403 case Duration_1_16:Note->Duration = Duration_1_8; break;
1400 case Duration_1_32:Note->Duration = Duration_1_16;break; 1404 case Duration_1_32:Note->Duration = Duration_1_16;break;
1401 } 1405 }
1402 Note->DurationSpec = NoSpecialDuration; 1406 Note->DurationSpec = NoSpecialDuration;
1403 } 1407 }
1404 /* Here happy creation */ 1408 /* Here happy creation */
1405 if (Note->DurationSpec == Length_2_3) { 1409 if (Note->DurationSpec == Length_2_3) {
1406 Note->DurationSpec = NoSpecialDuration; 1410 Note->DurationSpec = NoSpecialDuration;
1407 } 1411 }
1408 1412
1409 break; 1413 break;
1410 } 1414 }
1411 } 1415 }
1412 } 1416 }
1413 dest->NoteTone.NrCommands = NrNotes; 1417 dest->NoteTone.NrCommands = NrNotes;
1414 dbgprintf("speed = %i\n",Speed); 1418 dbgprintf("speed = %i\n",Speed);
1415 break; 1419 break;
1416 } 1420 }
1417 } 1421 }
1418 1422
1419 if (!foundlen) dest->NoteTone.NrCommands = 0; 1423 if (!foundlen) dest->NoteTone.NrCommands = 0;
1420} 1424}
1421 1425
1422 GSM_Error GSM_RingtoneConvert(GSM_Ringtone *dest, GSM_Ringtone *src, GSM_RingtoneFormatFormat) 1426 GSM_Error GSM_RingtoneConvert(GSM_Ringtone *dest, GSM_Ringtone *src, GSM_RingtoneFormatFormat)
1423{ 1427{
1424 dest->Format = Format; 1428 dest->Format = Format;
1425 CopyUnicodeString(dest->Name,src->Name); 1429 CopyUnicodeString(dest->Name,src->Name);
1426 if (src->Format==RING_NOTETONE && Format==RING_NOKIABINARY) { 1430 if (src->Format==RING_NOTETONE && Format==RING_NOKIABINARY) {
1427 RTTL2Binary(dest, src); 1431 RTTL2Binary(dest, src);
1428 return ERR_NONE; 1432 return ERR_NONE;
1429 } 1433 }
1430 if (src->Format==RING_NOKIABINARY && Format==RING_NOTETONE) { 1434 if (src->Format==RING_NOKIABINARY && Format==RING_NOTETONE) {
1431 Binary2RTTL(dest, src); 1435 Binary2RTTL(dest, src);
1432 return ERR_NONE; 1436 return ERR_NONE;
1433 } 1437 }
1434 /* The same source and target format */ 1438 /* The same source and target format */
1435 if (src->Format==Format) { 1439 if (src->Format==Format) {
1436 memcpy(dest,src,sizeof(GSM_Ringtone)); 1440 memcpy(dest,src,sizeof(GSM_Ringtone));
1437 return ERR_NONE; 1441 return ERR_NONE;
1438 } 1442 }
1439 return ERR_NOTIMPLEMENTED; 1443 return ERR_NOTIMPLEMENTED;
1440} 1444}
1441 1445
1442/* 0 = No header and footer, 0.5 = partial header and footer, 1446/* 0 = No header and footer, 0.5 = partial header and footer,
1443 * 1.0 = IMelody 1.0, 1.2 = IMelody 1.2 */ 1447 * 1.0 = IMelody 1.0, 1.2 = IMelody 1.2 */
1444unsigned char GSM_EncodeEMSSound(GSM_Ringtone ringtone, unsigned char *package, int *maxlength, double version, bool start) 1448unsigned char GSM_EncodeEMSSound(GSM_Ringtone ringtone, unsigned char *package, int *maxlength, double version, bool start)
1445{ 1449{
1446 int i, NrNotes = 0, Len, Max = *maxlength; 1450 int i, NrNotes = 0, Len, Max = *maxlength;
1447 1451
1448 GSM_RingNote *Note; 1452 GSM_RingNote *Note;
1449 1453
1450 GSM_RingNoteScaleDefNoteScale; 1454 GSM_RingNoteScaleDefNoteScale;
1451 GSM_RingNoteStyleDefNoteStyle=0; 1455 GSM_RingNoteStyleDefNoteStyle=0;
1452 int DefNoteTempo=0; 1456 int DefNoteTempo=0;
1453 1457
1454 bool started = false, end; 1458 bool started = false, end;
1455 1459
1456 *maxlength = 0; 1460 *maxlength = 0;
1457 1461
1458 if (start) { 1462 if (start) {
1459 if (version != 0) *maxlength+=sprintf(package,"BEGIN:IMELODY%c%c",13,10); 1463 if (version != 0) *maxlength+=sprintf(package,"BEGIN:IMELODY%c%c",13,10);
1460 if (version == 1.0) *maxlength+=sprintf(package+(*maxlength),"VERSION:1.0%c%c",13,10); 1464 if (version == 1.0) *maxlength+=sprintf(package+(*maxlength),"VERSION:1.0%c%c",13,10);
1461 if (version == 1.2) *maxlength+=sprintf(package+(*maxlength),"VERSION:1.2%c%c",13,10); 1465 if (version == 1.2) *maxlength+=sprintf(package+(*maxlength),"VERSION:1.2%c%c",13,10);
1462 if (version >= 1.0) *maxlength+=sprintf(package+(*maxlength),"FORMAT:CLASS1.0%c%c",13,10); 1466 if (version >= 1.0) *maxlength+=sprintf(package+(*maxlength),"FORMAT:CLASS1.0%c%c",13,10);
1463 if (version == 1.2) *maxlength+=sprintf(package+(*maxlength),"NAME:%s%c%c",DecodeUnicodeString(ringtone.Name),13,10); 1467 if (version == 1.2) *maxlength+=sprintf(package+(*maxlength),"NAME:%s%c%c",DecodeUnicodeString(ringtone.Name),13,10);
1464 } 1468 }
1465 1469
1466 DefNoteScale = Scale_880; /* by iMelody definition */ 1470 DefNoteScale = Scale_880; /* by iMelody definition */
1467 1471
1468 for (i=0;i<ringtone.NoteTone.NrCommands;i++) { 1472 for (i=0;i<ringtone.NoteTone.NrCommands;i++) {
1469 Len = *maxlength; 1473 Len = *maxlength;
1470 if (ringtone.NoteTone.Commands[i].Type != RING_Note) continue; 1474 if (ringtone.NoteTone.Commands[i].Type != RING_Note) continue;
1471 1475
1472 Note = &ringtone.NoteTone.Commands[i].Note; 1476 Note = &ringtone.NoteTone.Commands[i].Note;
1473 if (Note->Note == Note_Pause) continue; 1477 if (Note->Note == Note_Pause) continue;
1474 1478
1475 if (version == 1.2 && start) { 1479 if (version == 1.2 && start) {
1476 /* Save the default tempo */ 1480 /* Save the default tempo */
1477 DefNoteTempo = Note->Tempo; 1481 DefNoteTempo = Note->Tempo;
1478 Len+=sprintf(package+Len,"BEAT:%i%c%c",DefNoteTempo,13,10); 1482 Len+=sprintf(package+Len,"BEAT:%i%c%c",DefNoteTempo,13,10);
1479 dbgprintf("DefNoteTempo=%d\n",DefNoteTempo); 1483 dbgprintf("DefNoteTempo=%d\n",DefNoteTempo);
1480 1484
1481 /* Save default style */ 1485 /* Save default style */
1482 DefNoteStyle = Note->Style; 1486 DefNoteStyle = Note->Style;
1483 switch (DefNoteStyle) { 1487 switch (DefNoteStyle) {
1484 case NaturalStyle :Len+=sprintf(package+Len,"STYLE:S0%c%c",13,10); break; 1488 case NaturalStyle :Len+=sprintf(package+Len,"STYLE:S0%c%c",13,10); break;
1485 case ContinuousStyle:Len+=sprintf(package+Len,"STYLE:S1%c%c",13,10); break; 1489 case ContinuousStyle:Len+=sprintf(package+Len,"STYLE:S1%c%c",13,10); break;
1486 case StaccatoStyle :Len+=sprintf(package+Len,"STYLE:S2%c%c",13,10); break; 1490 case StaccatoStyle :Len+=sprintf(package+Len,"STYLE:S2%c%c",13,10); break;
1487 } 1491 }
1488 } 1492 }
1489 Len+=sprintf(package+Len,"MELODY:"); 1493 Len+=sprintf(package+Len,"MELODY:");
1490 if (version != 0) { 1494 if (version != 0) {
1491 /* 15 = Len of END:IMELODY... */ 1495 /* 15 = Len of END:IMELODY... */
1492 if ((Len+15) > Max) { end = true; break; } 1496 if ((Len+15) > Max) { end = true; break; }
1493 } else { 1497 } else {
1494 if (Len > Max) { end = true; break; } 1498 if (Len > Max) { end = true; break; }
1495 } 1499 }
1496 *maxlength = Len; 1500 *maxlength = Len;
1497 break; 1501 break;
1498 } 1502 }
1499 1503
1500 for (i=0;i<ringtone.NoteTone.NrCommands;i++) { 1504 for (i=0;i<ringtone.NoteTone.NrCommands;i++) {
1501 end = false; 1505 end = false;
1502 Len = *maxlength; 1506 Len = *maxlength;
1503 switch (ringtone.NoteTone.Commands[i].Type) { 1507 switch (ringtone.NoteTone.Commands[i].Type) {
1504 case RING_Note: 1508 case RING_Note:
1505 Note = &ringtone.NoteTone.Commands[i].Note; 1509 Note = &ringtone.NoteTone.Commands[i].Note;
1506 if (!started && Note->Note != Note_Pause) started = true; 1510 if (!started && Note->Note != Note_Pause) started = true;
1507 if (!started) break; 1511 if (!started) break;
1508 if (Note->Note!=Note_Pause && Note->Scale != DefNoteScale) { 1512 if (Note->Note!=Note_Pause && Note->Scale != DefNoteScale) {
1509 Len+=sprintf(package+Len,"*%i",Note->Scale-1); 1513 Len+=sprintf(package+Len,"*%i",Note->Scale-1);
1510 } 1514 }
1511 switch (Note->Note) { 1515 switch (Note->Note) {
1512 case Note_C :Len+=sprintf(package+Len,"c");break; 1516 case Note_C :Len+=sprintf(package+Len,"c");break;
1513 case Note_Cis:Len+=sprintf(package+Len,"#c");break; 1517 case Note_Cis:Len+=sprintf(package+Len,"#c");break;
1514 case Note_D :Len+=sprintf(package+Len,"d");break; 1518 case Note_D :Len+=sprintf(package+Len,"d");break;
1515 case Note_Dis:Len+=sprintf(package+Len,"#d");break; 1519 case Note_Dis:Len+=sprintf(package+Len,"#d");break;
1516 case Note_E :Len+=sprintf(package+Len,"e");break; 1520 case Note_E :Len+=sprintf(package+Len,"e");break;
1517 case Note_F :Len+=sprintf(package+Len,"f");break; 1521 case Note_F :Len+=sprintf(package+Len,"f");break;
1518 case Note_Fis:Len+=sprintf(package+Len,"#f");break; 1522 case Note_Fis:Len+=sprintf(package+Len,"#f");break;
1519 case Note_G :Len+=sprintf(package+Len,"g");break; 1523 case Note_G :Len+=sprintf(package+Len,"g");break;
1520 case Note_Gis:Len+=sprintf(package+Len,"#g");break; 1524 case Note_Gis:Len+=sprintf(package+Len,"#g");break;
1521 case Note_A :Len+=sprintf(package+Len,"a");break; 1525 case Note_A :Len+=sprintf(package+Len,"a");break;
1522 case Note_Ais:Len+=sprintf(package+Len,"#a");break; 1526 case Note_Ais:Len+=sprintf(package+Len,"#a");break;
1523 case Note_H :Len+=sprintf(package+Len,"b");break; 1527 case Note_H :Len+=sprintf(package+Len,"b");break;
1524 case Note_Pause :Len+=sprintf(package+Len,"r");break; 1528 case Note_Pause :Len+=sprintf(package+Len,"r");break;
1525 } 1529 }
1526 switch (Note->Duration) { 1530 switch (Note->Duration) {
1527 case Duration_Full : package[Len++]='0';break; 1531 case Duration_Full : package[Len++]='0';break;
1528 case Duration_1_2 : package[Len++]='1';break; 1532 case Duration_1_2 : package[Len++]='1';break;
1529 case Duration_1_4 : package[Len++]='2';break; 1533 case Duration_1_4 : package[Len++]='2';break;
1530 case Duration_1_8 : package[Len++]='3';break; 1534 case Duration_1_8 : package[Len++]='3';break;
1531 case Duration_1_16 : package[Len++]='4';break; 1535 case Duration_1_16 : package[Len++]='4';break;
1532 case Duration_1_32 : package[Len++]='5';break; 1536 case Duration_1_32 : package[Len++]='5';break;
1533 default : break; 1537 default : break;
1534 } 1538 }
1535 switch (Note->DurationSpec) { 1539 switch (Note->DurationSpec) {
1536 case DottedNote : package[Len++] = '.'; break; 1540 case DottedNote : package[Len++] = '.'; break;
1537 case DoubleDottedNote: package[Len++] = ':'; break; 1541 case DoubleDottedNote: package[Len++] = ':'; break;
1538 case Length_2_3 : package[Len++] = ';'; break; 1542 case Length_2_3 : package[Len++] = ';'; break;
1539 default : break; 1543 default : break;
1540 } 1544 }
1541 if (version != 0) { 1545 if (version != 0) {
1542 /* 15 = Len of END:IMELODY... */ 1546 /* 15 = Len of END:IMELODY... */
1543 if ((Len+15) > Max) { end = true; break; } 1547 if ((Len+15) > Max) { end = true; break; }
1544 } else { 1548 } else {
1545 if (Len > Max) { end = true; break; } 1549 if (Len > Max) { end = true; break; }
1546 } 1550 }
1547 *maxlength = Len; 1551 *maxlength = Len;
1548 break; 1552 break;
1549 case RING_DisableLED: 1553 case RING_DisableLED:
1550 if ((Len + 6) > Max) { end = true; break; } 1554 if ((Len + 6) > Max) { end = true; break; }
1551 (*maxlength)+=sprintf(package+Len,"ledoff"); 1555 (*maxlength)+=sprintf(package+Len,"ledoff");
1552 break; 1556 break;
1553 case RING_EnableLED: 1557 case RING_EnableLED:
1554 if ((Len + 5) > Max) { end = true; break; } 1558 if ((Len + 5) > Max) { end = true; break; }
1555 (*maxlength)+=sprintf(package+Len,"ledon"); 1559 (*maxlength)+=sprintf(package+Len,"ledon");
1556 break; 1560 break;
1557 case RING_DisableVibra: 1561 case RING_DisableVibra:
1558 if ((Len + 7) > Max) { end = true; break; } 1562 if ((Len + 7) > Max) { end = true; break; }
1559 (*maxlength)+=sprintf(package+Len,"vibeoff"); 1563 (*maxlength)+=sprintf(package+Len,"vibeoff");
1560 break; 1564 break;
1561 case RING_EnableVibra: 1565 case RING_EnableVibra:
1562 if ((Len + 6) > Max) { end = true; break; } 1566 if ((Len + 6) > Max) { end = true; break; }
1563 (*maxlength)+=sprintf(package+Len,"vibeon"); 1567 (*maxlength)+=sprintf(package+Len,"vibeon");
1564 break; 1568 break;
1565 case RING_DisableLight: 1569 case RING_DisableLight:
1566 if ((Len + 7) > Max) { end = true; break; } 1570 if ((Len + 7) > Max) { end = true; break; }
1567 (*maxlength)+=sprintf(package+Len,"backoff"); 1571 (*maxlength)+=sprintf(package+Len,"backoff");
1568 break; 1572 break;
1569 case RING_EnableLight: 1573 case RING_EnableLight:
1570 if ((Len + 6) > Max) { end = true; break; } 1574 if ((Len + 6) > Max) { end = true; break; }
1571 (*maxlength)+=sprintf(package+Len,"backon"); 1575 (*maxlength)+=sprintf(package+Len,"backon");
1572 break; 1576 break;
1573 default: 1577 default:
1574 break; 1578 break;
1575 } 1579 }
1576 if (end) break; 1580 if (end) break;
1577 NrNotes ++; 1581 NrNotes ++;
1578 } 1582 }
1579 1583
1580 if (version != 0) *maxlength+=sprintf(package+(*maxlength),"%c%cEND:IMELODY%c%c",13,10,13,10); 1584 if (version != 0) *maxlength+=sprintf(package+(*maxlength),"%c%cEND:IMELODY%c%c",13,10,13,10);
1581 1585
1582 return NrNotes; 1586 return NrNotes;
1583} 1587}
1584 1588
1585char *GSM_GetRingtoneName(GSM_AllRingtonesInfo *Info, int ID) 1589char *GSM_GetRingtoneName(GSM_AllRingtonesInfo *Info, int ID)
1586{ 1590{
1587 int i; 1591 int i;
1588 static char ala[2]; 1592 static char ala[2];
1589 1593
1590 for (i=0;i<Info->Number;i++) { 1594 for (i=0;i<Info->Number;i++) {
1591 if (Info->Ringtone[i].ID == ID) return Info->Ringtone[i].Name; 1595 if (Info->Ringtone[i].ID == ID) return Info->Ringtone[i].Name;
1592 } 1596 }
1593 1597
1594 ala[0] = 0; 1598 ala[0] = 0;
1595 ala[1] = 0; 1599 ala[1] = 0;
1596 return ala; 1600 return ala;
1597} 1601}
1598 1602
1599/* How should editor hadle tabs in this file? Add editor commands here. 1603/* How should editor hadle tabs in this file? Add editor commands here.
1600 * vim: noexpandtab sw=8 ts=8 sts=8: 1604 * vim: noexpandtab sw=8 ts=8 sts=8:
1601 */ 1605 */