編輯:關於android開發
參數fname為mix文件在系統中的位置,buf為讀取文件數據存放的緩沖區,maxlen為buf的最大長度。
- int load_mixer_file(const char *fname, char *buf, unsigned maxlen)
來交給具體的設備處理。
- int ret = ioctl(dev, MIXERIOCLOADBUF, (unsigned long)buf);
- /** simple channel scaler */
- struct mixer_scaler_s {
- floatnegative_scale;//負向縮放, MIX文件中 O: 後面的第1個整數/10000.0f
- floatpositive_scale;//正向縮放, MIX文件中 O: 後面的第2個整數/10000.0f
- floatoffset; //偏移 , MIX文件中 O: 後面的第3個整數/10000.0f
- floatmin_output;//最小輸出值 , MIX文件中 O: 後面的第4個整數/10000.0f
- floatmax_output;//最大輸出值 , MIX文件中 O: 後面的第5個整數/10000.0f
- };//該結構定義了單個控制量的結構
- /** mixer input */
- struct mixer_control_s {
- uint8_tcontrol_group;/**< group from which the input reads */
- uint8_tcontrol_index;/**< index within the control group */
- struct mixer_scaler_s scaler;/**< scaling applied to the input before use */
- };//定義輸入量的結構
- /** simple mixer */
- struct mixer_simple_s {
- uint8_tcontrol_count;/**< number of inputs */
- struct mixer_scaler_soutput_scaler;/**< scaling for the output */
- struct mixer_control_scontrols[0];/**< actual size of the array is set by control_count */
- };//定義了一個控制實體的控制體,包括輸入的信號數量,輸入信號控制集,輸出信號控制。
- //因為一個mixer只有一個輸出,可以有0到多個輸入,所以control_count指明了這個mixer所需要的輸入信號數量,而具體的信號都存放在數組controls[0]中。
- //輸出則由output_scaler來控制.
- //從這些結構體的定義,可以對照起來mix文件語法的定義.
- int MixerGroup::load_from_buf(const char *buf, unsigned &buflen)
- {
- int ret = -1;
- const char *end = buf + buflen;
- /*
- * Loop until either we have emptied the buffer, or we have failed to
- * allocate something when we expected to.
- */
- while (buflen > 0) {
- Mixer *m = nullptr;
- const char *p = end - buflen;
- unsigned resid = buflen;
- /*
- * Use the next character as a hint to decide which mixer class to construct.
- */
- switch (*p) {//首先看該行的第一個字母,來確定數據的類別.
- case 'Z':
- m = NullMixer::from_text(p, resid);
- break;
- case 'M':
- m = SimpleMixer::from_text(_control_cb, _cb_handle, p, resid);
- break;
- case 'R':
- m = MultirotorMixer::from_text(_control_cb, _cb_handle, p, resid);
- break;
- default:
- /* it's probably junk or whitespace, skip a byte and retry */
- buflen--;
- continue;
- }
- /*
- * If we constructed something, add it to the group.
- */
- if (m != nullptr) {
- add_mixer(m);
- /* we constructed something */
- ret = 0;
- /* only adjust buflen if parsing was successful */
- buflen = resid;
- debug("SUCCESS - buflen: %d", buflen);
- } else {
- /*
- * There is data in the buffer that we expected to parse, but it didn't,
- * so give up for now.
- */
- break;
- }
- }
- /* nothing more in the buffer for us now */
- return ret;
- }
- SimpleMixer *
- SimpleMixer::from_text(Mixer::ControlCallback control_cb, uintptr_t cb_handle, const char *buf, unsigned &buflen)
- {
- SimpleMixer *sm = nullptr;
- mixer_simple_s *mixinfo = nullptr;
- unsigned inputs;
- int used;
- const char *end = buf + buflen;
- /* get the base info for the mixer */
- if (sscanf(buf, "M: %u%n", &inputs, &used) != 1) {
- debug("simple parse failed on '%s'", buf);
- goto out;
- }//復制M:後面第一個數值到無符號整型數據到變量inputs中,並將已經處理的字條數目賦值給used
- buf = skipline(buf, buflen);//讓buf指定下一行
- if (buf == nullptr) {
- debug("no line ending, line is incomplete");
- goto out;
- }
- mixinfo = (mixer_simple_s *)malloc(MIXER_SIMPLE_SIZE(inputs));
- //M:後面的數字為struct mixer_control_s 結構的數量.MIXER_SIMPLE_SIZE的字義為sizeof(mixer_simple_s) + inputs*sizeof(mixer_control_s),
- //即一個完整的mixer_simple_s的定義,controls[0]一共有inputs個.
- if (mixinfo == nullptr) {
- debug("could not allocate memory for mixer info");
- goto out;
- }
- mixinfo->control_count = inputs;//input 信號的數量
- if (parse_output_scaler(end - buflen, buflen, mixinfo->output_scaler)) {
- debug("simple mixer parser failed parsing out scaler tag, ret: '%s'", buf);
- goto out;
- }//該函數解析輸出域,並將期填充到mixinfo的output_scaler字段中.
- int SimpleMixer::parse_output_scaler(const char *buf, unsigned &buflen, mixer_scaler_s &scaler)
- {
- int ret;
- int s[5];
- int n = -1;
- buf = findtag(buf, buflen, 'O');//尋找"O:"這樣的控制符,返回指針指向輸出格式域定義的首字符'O'.
- if ((buf == nullptr) || (buflen < 12)) {
- debug("output parser failed finding tag, ret: '%s'", buf);
- return -1;
- }//12,表示O:這行的定義至少有12個字符(O:和五個1位長的整數),例如最短的定義為: O: 0 0 0 0 0
- if ((ret = sscanf(buf, "O: %d %d %d %d %d %n",//O:後面必須有5個整數,且整數間用至少一個空格分開,此處是取出O:後面的5個整數值.
- &s[0], &s[1], &s[2], &s[3], &s[4], &n)) != 5) {
- debug("out scaler parse failed on '%s' (got %d, consumed %d)", buf, ret, n);
- return -1;
- }
- buf = skipline(buf, buflen);
- if (buf == nullptr) {
- debug("no line ending, line is incomplete");
- return -1;
- }
- //從下面的賦值操作可以得出 O:後面5個數值的字義.,分別為 [negative_scale] [positive_scale] [offset] [min_output] [max_output]
- //並且每個這都做了除10000的操作,所以MIX格式定義中說這些值都是被放大10000倍後的數值.
- scaler.negative_scale= s[0] / 10000.0f;
- scaler.positive_scale= s[1] / 10000.0f;
- scaler.offset= s[2] / 10000.0f;
- scaler.min_output= s[3] / 10000.0f;
- scaler.max_output= s[4] / 10000.0f;
- return 0;
- }
//上面解析了MIXER的輸出量,下面開始解析輸入量,因為我們已經讀取了輸入信號的數量("M: n"中n定義的數值),所以要循環n次.- //首先記住parse_control_scaler函數輸入的參數
- for (unsigned i = 0; i < inputs; i++) {
- if (parse_control_scaler(end - buflen, buflen,
- mixinfo->controls[i].scaler,
- mixinfo->controls[i].control_group,
- mixinfo->controls[i].control_index)) {
- debug("simple mixer parser failed parsing ctrl scaler tag, ret: '%s'", buf);
- goto out;
- }
- }
- int SimpleMixer::parse_control_scaler(const char *buf, unsigned &buflen, mixer_scaler_s &scaler, uint8_t &control_group,
- uint8_t &control_index)
- {
- unsigned u[2];
- int s[5];
- buf = findtag(buf, buflen, 'S');//找到剩余緩沖區中的第一個'S',並讓buf指向該行的行首;
- //
- //16表示該S:行至少有16個字符,即至少有7個整數(因為整數間至少有1個空格分隔)
- if ((buf == nullptr) || (buflen < 16)) {
- debug("control parser failed finding tag, ret: '%s'", buf);
- return -1;
- }
- //讀取S:後面的7個整數.
- if (sscanf(buf, "S: %u %u %d %d %d %d %d",
- &u[0], &u[1], &s[0], &s[1], &s[2], &s[3], &s[4]) != 7) {
- debug("control parse failed on '%s'", buf);
- return -1;
- }
- buf = skipline(buf, buflen);
- if (buf == nullptr) {
- debug("no line ending, line is incomplete");
- return -1;
- }
- //從下面的賦值可以看出MIXER文件S:定義的格式,S:後面的整數分別為
- // [control_group] [ontrol_index] [negative_scale] [positive_scale] [offset] [min_output] [max_output]
- // 可以看出,輸入信號的定義比輸入出信號的定義多了兩個整數,用來表示當前輸入信號所在的組和組內的序號. 第1和第2個整就是用來
- // 說明組號和組內序號.而後面5個整數的定義和輸入信號的定義一樣,且也要除以10000.
- control_group= u[0];
- control_index= u[1];
- scaler.negative_scale= s[0] / 10000.0f;
- scaler.positive_scale= s[1] / 10000.0f;
- scaler.offset= s[2] / 10000.0f;
- scaler.min_output= s[3] / 10000.0f;
- scaler.max_output= s[4] / 10000.0f;
- return 0;
- }
- sm = new SimpleMixer(control_cb, cb_handle, mixinfo);
- if (sm != nullptr) {
- mixinfo = nullptr;
- debug("loaded mixer with %d input(s)", inputs);
- } else {
- debug("could not allocate memory for mixer");
- }
- out:
- if (mixinfo != nullptr) {
- free(mixinfo);
- }
- return sm;
- }
Android專用Log開源項目——KLog 在Android開發和調試的過程中,Log的使用是非常頻繁的,一個好的Log工具可以幫你節省很多時間,所以凱子哥抽空寫了個
常見bug,bug 錯誤日志圖 被這弱智的錯誤吭了半個小時,項目本來好好的,然後因為改版加了很多東西,所以就超限了,一開始總是報下面那圖的錯,搞的我總以為
Android立體旋轉動畫實現與封裝(支持以X、Y、Z三個軸為軸心旋轉),android立體旋轉本文主要介紹Android立體旋轉動畫,或者3D旋轉,下圖是我自己實現的一
Linux內核調試技術——進程D狀態死鎖檢測Linux的進程存在多種狀態,如TASK_RUNNING的運行態、EXIT_DEAD的停止態和TASK_INTERRUPTIB
ErrorExecution failed for task '