gn_error playringtone(int argc, char *argv[], gn_data *data, struct gn_statemachine *state) { gn_ringtone ringtone; gn_tone tone; gn_error error; char *filename = optarg; int i, ulen; struct timeval dt; #if (defined HAVE_TIMEOPS) && (defined HAVE_GETTIMEOFDAY) struct timeval t1, t2; #endif int volume = 5; struct option options[] = { { "volume", required_argument, NULL, 'v'}, { NULL, 0, NULL, 0} }; while ((i = getopt_long(argc, argv, "v:", options, NULL)) != -1) { switch (i) { case 'v': volume = gnokii_atoi(optarg); if (errno || volume < 0) return playringtone_usage(stderr, -1); break; default: return playringtone_usage(stderr, -1); } } if (argc > optind) { /* There are too many arguments that don't start with '-' */ return playringtone_usage(stderr, -1); } memset(&ringtone, 0, sizeof(ringtone)); memset(&tone, 0, sizeof(tone)); gn_data_clear(data); data->ringtone = &ringtone; data->tone = &tone; if (!filename) { fprintf(stderr, _("Internal gnokii error: null filename\n")); return GN_ERR_FAILED; } if ((error = gn_file_ringtone_read(filename, &ringtone))) { fprintf(stderr, _("Failed to load ringtone: %s\n"), gn_error_print(error)); return error; } #if (defined HAVE_TIMEOPS) && (defined HAVE_GETTIMEOFDAY) gettimeofday(&t1, NULL); tone.frequency = 0; tone.volume = 0; gn_sm_functions(GN_OP_PlayTone, data, state); gettimeofday(&t2, NULL); timersub(&t2, &t1, &dt); #else dt.tv_sec = 0; dt.tv_usec = 20000; #endif signal(SIGINT, interrupted); for (i = 0; !bshutdown && i < ringtone.notes_count; i++) { tone.volume = volume; gn_ringtone_get_tone(&ringtone, i, &tone.frequency, &ulen); if ((error = gn_sm_functions(GN_OP_PlayTone, data, state)) != GN_ERR_NONE) break; if (ulen > 2 * dt.tv_usec + 20000) usleep(ulen - 2 * dt.tv_usec - 20000); tone.volume = 0; if ((error = gn_sm_functions(GN_OP_PlayTone, data, state)) != GN_ERR_NONE) break; usleep(20000); } tone.frequency = 0; tone.volume = 0; gn_sm_functions(GN_OP_PlayTone, data, state); if (error == GN_ERR_NONE) fprintf(stderr, _("Play succeeded!\n")); else fprintf(stderr, _("Play failed: %s\n"), gn_error_print(error)); return error; }
gn_error pnok_ringtone_to_raw(char *raw, int *rawlen, const gn_ringtone *ringtone, int dct4) { int i, c, p, l, freq, base; int rleft, vtime, vstat; const gn_ringtone_note *note; char header[] = {0x00, 0x02, 0xfc, 0x0a, 0x01}; char tailer[] = {0x0a, 0x0a, 0x0a, 0xfe, 0x40, 0x20, 0x07, 0x0b, 0xff, 0xff, 0xff, 0xff}; char vibr_on[] = {0x0a, 0x01}; char vibr_off[] = {0x0a, 0xfe}; int notes[] = {0, 1, 2, 3, 4, 4, 5, 6, 7, 8, 9, 10, 11, 11}; rleft = *rawlen; vtime = 0; vstat = 1; base = dct4 ? 90 : 114; if (rleft < sizeof(header)) return GN_ERR_MEMORYFULL; memcpy(raw, header, sizeof(header)); raw += sizeof(header); rleft -= sizeof(header); for (i = 0; i < ringtone->notes_count; i++) { if (vtime >= 300) { if (rleft < 2) return GN_ERR_MEMORYFULL; memcpy(raw, vstat ? vibr_off : vibr_on, 2); vtime = 0; vstat = !vstat; raw += 2; rleft -= 2; } note = ringtone->notes + i; gn_ringtone_get_tone(ringtone, i, &freq, &p); p /= 8000; vtime += p; if (note->note == 0xff) { c = 0x40; p++; } else { c = 12 * (note->note / 14) + notes[note->note % 14] + base; } while (p > 1) { if (rleft < 2) return GN_ERR_MEMORYFULL; l = (p > 0xff) ? 0xff : p - 1; *raw++ = c; *raw++ = l; p -= l; rleft -= 2; } if (c != 0x40) { if (rleft < 2) return GN_ERR_MEMORYFULL; *raw++ = 0x40; *raw++ = 1; rleft -= 2; } } if (rleft < sizeof(tailer)) return GN_ERR_MEMORYFULL; memcpy(raw, tailer, sizeof(tailer)); rleft -= sizeof(tailer); *rawlen = (*rawlen - rleft) & ~3; return GN_ERR_NONE; }